package com.zondy.mapgis.android.view;

import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Rect;
import android.location.GpsSatellite;
import android.view.SurfaceHolder;

import com.zondy.mapgis.explorer.R;

/**
 * 画罗盘和卫星线程。 每次销毁SatelliteView时将thread的isRunning设为false，则其不再绘制视图。
 * 每次重建SatelliteView时重新创建thread。
 */
public class DrawSatellitesThread extends Thread
{

	private Context context;
	// private Bitmap backBitmap;
	// 卫星及罗盘，画星云图
	private Bitmap satelliteBitmap;
	private Bitmap compassBitmap;
	private final int[] mStatelliteIco = {R.drawable.ico_drop_red,R.drawable.ico_drop_blue, R.drawable.ico_drop_yellow, R.drawable.ico_drop_lightgreen, R.drawable.ico_drop_green,
			R.drawable.satellite_point, };
	// 创建画笔
	Paint paint;
	// 创建SurfaceHolder对象
	private SurfaceHolder surfaceHolder;
	// 是否运行控制
	private boolean isRunning = false;
	private int cx = 0;
	private int cy = 0;
	// 星云图半径
	private int compassRadius = 420 / 2;

	PaintFlagsDrawFilter paintdrawfilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);

	public static final LinkedBlockingQueue<List<GpsSatellite>> queue = new LinkedBlockingQueue<List<GpsSatellite>>(60);

	public DrawSatellitesThread(SurfaceHolder holder, Context context)
	{
		this.context = context;
		this.surfaceHolder = holder;
		Resources resources = context.getResources();
		// backBitmap = BitmapFactory.decodeResource(resources,
		// R.color.whitewarm);

		// 获取星云图片
		compassBitmap = BitmapFactory.decodeResource(resources, R.drawable.compass_star);
		// 获取图片半径
		compassRadius = compassBitmap.getWidth() / 2;
		// 获取卫星图片
		satelliteBitmap = BitmapFactory.decodeResource(resources, R.drawable.satellite_point);
		// 初始化画笔，并进行相关设置
		paint = new Paint();
		paint.setSubpixelText(true);
		// 抗锯齿
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		// 画笔颜色
		paint.setColor(Color.CYAN);
		// 文字大小
		paint.setTextSize(24);
		// 文字位置
		paint.setTextAlign(Align.CENTER);
	}

	/**
	 * 方法名：setSurfaceSize 功能：回调函数，当surface的大小改变时调用
	 * 
	 * @param width
	 * @param height
	 */
	public void setSurfaceSize(int width, int height)
	{
		synchronized (surfaceHolder)
		{
			cx = width / 2;
			cy = height / 2;
		}
	}

	@Override
	public void run()
	{
		// 定义卫星集合
		List<GpsSatellite> list = null;
		// 定义画布
		Canvas canvas = null;

		try
		{
			canvas = surfaceHolder.lockCanvas(null);
			// 初始化画布中心坐标
			cx = canvas.getWidth() / 2;
			cy = canvas.getHeight() / 2;
			synchronized (surfaceHolder)
			{
				// 执行doDraw方法
				doDraw(canvas, null);
			}

		}
		finally
		{
			if (canvas != null)
			{
				surfaceHolder.unlockCanvasAndPost(canvas);
			}
		}

		// 如果SatelliteView被销毁了又重建，可能存在多个绘制thread，这里处理一下。
		// 每次销毁SatelliteView时都把当前的thread的isCurrentThread设为false；
		while (isRunning)
		{
			try
			{
				list = queue.take();
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			try
			{
				canvas = surfaceHolder.lockCanvas(null);
				synchronized (surfaceHolder)
				{
					doDraw(canvas, list);
				}
			}
			finally
			{
				if (canvas != null)
				{
					surfaceHolder.unlockCanvasAndPost(canvas);
				}
			}
		}
	}

	/**
	 * 方法名：setRunning 功能：设置是否运行
	 * 
	 * @param b
	 */
	public void setRunning(boolean b)
	{
		isRunning = b;
	}

	/**
	 * 方法名：repaintSatellites 功能：重画卫星集合
	 * 
	 * @param list
	 */
	public void repaintSatellites(List<GpsSatellite> list)
	{
		synchronized (surfaceHolder)
		{
			try
			{
				queue.offer(list);
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
		}
	}

	/**
	 * 方法名：drawBackground 功能：绘制背景罗盘
	 * 
	 * @param canvas
	 * @param cx
	 * @param cy
	 * @param r
	 */
	private void drawBackground(Canvas canvas, int cx, int cy, int r)
	{
		// 在屏幕较大的设备中，由于backbitmap高宽比与设备不匹配会导致星云图下面可能有黑边，这里把图片放大一下，避免该问题。

		//  在10寸的设备上星云图显示比较小，所以放大一些
		int widBitmap = compassBitmap.getWidth();
		int heiBitmap = compassBitmap.getHeight();

		Rect rect = this.surfaceHolder.getSurfaceFrame();

		float fWidScale = 1f;
		float fHeiScale = 1f;
		if (rect.width() > widBitmap)
		{
			fWidScale = rect.width() / (float) widBitmap;
		}
		if (rect.height() > heiBitmap)
		{
			fHeiScale = rect.height() / (float) heiBitmap;
		}
		Matrix matrix = new Matrix();
		matrix.postScale(fWidScale, fHeiScale);
		Bitmap bitmap = Bitmap.createBitmap(compassBitmap, 0, 0, compassBitmap.getWidth(), compassBitmap.getHeight(), matrix, false);

		//绘制方式一
//		canvas.drawColor(context.getResources().getColor(R.color.white));
//		canvas.drawBitmap(bitmap, 0, 0, paint);

		 int x = cx - r;
		 int y = cy - r;
		 canvas.drawColor(context.getResources().getColor(R.color.white));
		 canvas.drawBitmap(compassBitmap, x, y, paint);
	}

	/**
	 * 方法名：degreeToRadian 功能：将角度转换为弧度，以用于三角函数的运算
	 * 
	 * @param degree
	 * @return
	 */
	private double degreeToRadian(double degree)
	{
		return (degree * Math.PI) / 180.0d;
	}

	/**
	 * 方法名：snrToSignalLevel 功能：将snr转为转化为通用的信号强度级别
	 * 
	 * @param snr
	 * @return
	 */
	@SuppressWarnings("unused")
	private int snrToSignalLevel(float snr)
	{
		int level = 0;
		if (snr >= 0 && snr < 5)
		{
//			level = 4;
			level = 1;
		}
		else if (snr >= 5 && snr < 10)
		{
//			level = 5;
			level = 2;
		}
		else if (snr >= 10 && snr < 50)
		{
			level = 3;
		}
		else if (snr >= 50 && snr < 100)
		{
			level = 4;
		}
		else if (snr >= 100 && snr < 500)
		{
			level = 5;
		}
		else if (snr >= 500)
		{
			level = 6;
		}
		return level;
	}

	/**
	 * 方法名：drawSatellite 功能：在罗盘背景上画卫星位置
	 * 
	 * @param canvas
	 * @param satellite
	 * @param cx
	 * @param cy
	 * @param r
	 */
	private void drawSatellite(Canvas canvas, GpsSatellite satellite, int cx, int cy, int r)
	{

		// 得到仰角
		float elevation = satellite.getElevation();
		// 通过仰角，计算出这个卫星应该绘制到离圆心多远的位置，这里用的是角度的比值
		/**
		 * @content <修改说明> 修改卫星离圆心的距离 （除以2）
		 * @author admin 2017-1-17 下午4:04:53
		 */
		double r2 = r * ((90.0f - elevation) / 90.0f) / 2;
		// 得到方位角,在计算X，Y座标的三角函数时，要做转换
		double azimuth = satellite.getAzimuth();

		/*
		 * 转换成XY座标系中的夹角,方位角是与正北向也就是Y轴顺时针方向的夹角， 注意我们通常几何上的角度是与X轴正向的逆时针方向的夹角）,
		 * 在计算X，Y座标的三角函数时，要做转换
		 */
		double radian = degreeToRadian(360 - azimuth + 90);
		// 计算卫星的x，y坐标位置
		double x = cx + Math.cos(radian) * r2;
		double y = cy + Math.sin(radian) * r2;
		
		// 在卫星图标的位置上绘出文字（卫星编号及信号强度）
		int snr = (int) satellite.getSnr();// 卫星的信噪比，浮点型数据
		int signLevel = snrToSignalLevel(snr); // 转换后的通用信号等级（暂时不用）
		// 卫星的伪随机噪声码，整形数据
		String info = String.format("%s", satellite.getPrn());
		canvas.drawText(info, (float) (x), (float) (y), paint);
		
		// 得到卫星图标的半径
		int sr = satelliteBitmap.getWidth() / 2;
		// 以x,y为中心绘制卫星图标
		canvas.drawBitmap(getSatelliteBmp(mStatelliteIco[signLevel]), (float) (x - sr), (float) (y - sr), paint);
	}

	/**
	 * 方法名：doDraw 功能：在surface上绘制背景罗盘以及卫星位置
	 * 
	 * @param canvas
	 * @param satellites
	 */
	private void doDraw(Canvas canvas, List<GpsSatellite> satellites)
	{
		if (canvas != null)
		{
			// 绘制背景罗盘
			drawBackground(canvas, cx, cy, compassRadius);
			// 绘制卫星分布
			if (satellites != null)
			{
				for (GpsSatellite satellite : satellites)
				{
					drawSatellite(canvas, satellite, cx, cy, compassRadius);
				}
			}
		}
	}

	/**
	 * 根据bmpID获取卫星图片
	 * 
	 * @param bmpID
	 * @return
	 */
	private Bitmap getSatelliteBmp(int bmpID)
	{
		return BitmapFactory.decodeResource(context.getResources(), bmpID);
	}

}
